#include <iostream>
#include <chrono>
#include <atomic>
#include <mutex>
#include <thread>
#include "../include/noncopyable.h"


/*

datacenterId (数据中心ID):

类型：int64_t
含义：这个参数用于标识数据中心的唯一ID。在分布式系统中，可能会有多个数据中心，每个数据中心需要有一个唯一的标识符，以便在生成唯一ID时能够区分不同的数据中心。
重要性：数据中心ID是构成最终唯一ID的一部分，确保了即使在不同数据中心生成的ID也不会冲突。
machineId (机器ID):

类型：int64_t
含义：这个参数用于标识在同一数据中心内部的不同机器的唯一ID。每个数据中心内可能有多台机器，每台机器也需要一个唯一的标识符。
重要性：机器ID同样是构成最终唯一ID的一部分，确保了即使在同一数据中心内，不同机器生成的ID也不会冲突。
sequence (序列号):

类型：int64_t
含义：这个参数用于在同一毫秒内生成多个唯一ID时的序列号。由于雪花算法的时间戳精度到毫秒，如果在同一毫秒内有多个ID生成请求，就需要通过序列号来区分这些请求。
默认值：0
重要性：序列号确保了在同一毫秒内生成的ID是唯一的，是雪花算法实现高并发下唯一ID生成的关键部分。
在构造函数中，还调用了 isValidId 方法来校验 datacenterId 和 machineId 是否在合法的范围内。如果任何一个ID超出了其最大值（MAX_DATACENTER_ID 或 MAX_MACHINE_ID），就会抛出一个 std::invalid_argument 异常，提示“ID out of range”。

需要注意的是，sequence 参数在构造函数中并没有特别的校验逻辑，因为序列号是在运行时动态分配的，并且受到 SEQUENCE_MASK 的限制，以确保其值不会超出允许的范围。
*/

class SnowflakeIdGenerator
{
public:
    SnowflakeIdGenerator(int64_t datacenterId, int64_t machineId, int64_t sequence = 0)
        : datacenterId_(datacenterId), machineId_(machineId), sequence_(sequence), lastTimestamp_(-1)
    {
        if (!isValidId(datacenterId, MAX_DATACENTER_ID) || !isValidId(machineId, MAX_MACHINE_ID))
        {
            throw std::invalid_argument("ID out of range");
        }
    }

    int64_t nextId()
    {
        int64_t timestamp = timeGen();

        while (timestamp <= lastTimestamp_)
        {
            timestamp = timeGen();
            if (timestamp < lastTimestamp_)
            {
                throw std::runtime_error("Clock moved backwards. Refusing to generate id");
            }
        }

        int64_t newSequence = (sequence_ + 1) & SEQUENCE_MASK;
        if (newSequence == 0)
        {
            timestamp = tilNextMillis(lastTimestamp_);
            newSequence = sequence_ + 1;
        }

        std::atomic_store(&lastTimestamp_, timestamp);
        std::atomic_store(&sequence_, newSequence);

        return ((timestamp - TWEPOCH) << TIMESTAMP_LEFT_SHIFT) |
               (datacenterId_ << DATACENTER_ID_SHIFT) |
               (machineId_ << MACHINE_ID_SHIFT) |
               newSequence;
    }

private:
    int64_t timeGen()
    {
        return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
    }

    int64_t tilNextMillis(int64_t lastTimestamp)
    {
        int64_t timestamp = timeGen();
        while (timestamp <= lastTimestamp)
        {
            timestamp = timeGen();
        }
        return timestamp;
    }

    bool isValidId(int64_t id, int64_t maxId)
    {
        return id >= 0 && id <= maxId;
    }

private:
    const int64_t TWEPOCH = 1288834974657L;
    const int64_t MAX_DATACENTER_ID = -1L ^ (-1L << 5); // 假设数据中心ID为5位
    const int64_t MAX_MACHINE_ID = -1L ^ (-1L << 5);    // 假设机器ID为5位
    const int64_t SEQUENCE_MASK = -1L ^ (-1L << 12);    // 假设序列号为12位

    const int64_t DATACENTER_ID_SHIFT = 12;
    const int64_t MACHINE_ID_SHIFT = 12 + 5;
    const int64_t TIMESTAMP_LEFT_SHIFT = 12 + 5 + 5;

    int64_t datacenterId_;
    int64_t machineId_;
    std::atomic<int64_t> sequence_;
    std::atomic<int64_t> lastTimestamp_;
};

SnowflakeIdGenerator* GetInstance()
{
    static SnowflakeIdGenerator ins(0xefffe,0xafffe);
    return &ins;
}